/*
 * Copyright (c) 2009, Jan Pastor. All Rights Reserved.
 */

package sk.jp.jitag.util;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.plaf.metal.DefaultMetalTheme;
import javax.swing.plaf.metal.OceanTheme;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jgoodies.looks.plastic.theme.DesertBlue;
import com.jgoodies.looks.plastic.theme.DesertBluer;
import com.jgoodies.looks.plastic.theme.ExperienceBlue;
import com.jgoodies.looks.plastic.theme.LightGray;
import com.jgoodies.looks.plastic.theme.Silver;
import com.jgoodies.looks.plastic.theme.SkyBlue;

import de.javasoft.plaf.synthetica.*;
import sk.jp.commons.utils.CollectionUtils;
import sk.jp.commons.utils.LogMsg;
import sk.jp.jitag.model.config.MediaTypeClass;
import sk.jp.jitag.ui.common.Icons;

/**
 * Default values or a sets of supported values.
 */
public class Defaults {

    private static final Logger log = LoggerFactory.getLogger(Defaults.class);

    private Defaults() {
    }

    public static enum ConfigPlace {
        app,  //application working directory
        user, //user's home (~/.jitag) directory
        path; //specified path
    }

    public static final Map<MediaTypeClass.Items,String> mediaTypeLabel;
    static {
        mediaTypeLabel = new LinkedHashMap<MediaTypeClass.Items, String>(5);
        mediaTypeLabel.put(MediaTypeClass.Items.image, Msg.defaultsMediaClassImage.value());
        mediaTypeLabel.put(MediaTypeClass.Items.text, Msg.defaultsMediaClassText.value());
        mediaTypeLabel.put(MediaTypeClass.Items.audio, Msg.defaultsMediaClassAudio.value());
        mediaTypeLabel.put(MediaTypeClass.Items.video, Msg.defaultsMediaClassVideo.value());
        mediaTypeLabel.put(MediaTypeClass.Items.other, Msg.defaultsMediaClassOther.value());
    }

    public static final Map<MediaTypeClass.Items,Icons> mediaTypeIcon;
    static {
        mediaTypeIcon = new LinkedHashMap<MediaTypeClass.Items,Icons>(5);
        mediaTypeIcon.put(MediaTypeClass.Items.image, Icons.image);
        mediaTypeIcon.put(MediaTypeClass.Items.text, Icons.text);
        mediaTypeIcon.put(MediaTypeClass.Items.audio, Icons.audio);
        mediaTypeIcon.put(MediaTypeClass.Items.video, Icons.video);
        mediaTypeIcon.put(MediaTypeClass.Items.other, Icons.other);
    }

    public static enum LafClass {
        metal("javax.swing.plaf.metal.MetalLookAndFeel"),
        windows("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"),
        gtk("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"),
        synthetica("de.javasoft.plaf.synthetica.SyntheticaStandardLookAndFeel"),
        jgoodiesWin("com.jgoodies.looks.windows.WindowsLookAndFeel"),
        jgoodiesPl("com.jgoodies.looks.plastic.PlasticLookAndFeel"),
        jgoodiesPl3D("com.jgoodies.looks.plastic.Plastic3DLookAndFeel"),
        jgoodiesPlXp("com.jgoodies.looks.plastic.PlasticXPLookAndFeel"),
        quaqua("ch.randelshofer.quaqua.QuaquaLookAndFeel"),
        ;
        private String className;
        private LafClass(String className) {
            this.className = className;
        }
        public String getClassName() {
            return className;
        }
    }

    /**
     * {locale id -> language name}
     */
    public static final Map<String,String> locales = new LinkedHashMap<String, String>();
    static {
        locales.put("en", "English");
        locales.put("sk", "Slovenčina");
    }

    /**
     * {label -> seconds/null}
     */
    public static final Map<String,String> scanPeriods = new LinkedHashMap<String,String>();
    static {
        scanPeriods.put(Msg.defaultsScanPeriodsPresets.value(), "");//Presets
        scanPeriods.put(Msg.defaultsScanPeriods5min.value(), ""+(60*5));//5 min
        scanPeriods.put(Msg.defaultsScanPeriods15min.value(), ""+(60*15));//15 min
        scanPeriods.put(Msg.defaultsScanPeriods1hour.value(), ""+(60*60));//1 hour
        scanPeriods.put(Msg.defaultsScanPeriods1day.value(), ""+(60*60*24));//1 day
        scanPeriods.put(Msg.defaultsScanPeriodsNoScan.value(), "");//No auto scan
    }

    /**
     * {L&F class -> L&F label}
     */
    public static final Map<String,String> lafs = new LinkedHashMap<String, String>();
    static {
        lafs.put(LafClass.metal.getClassName(), "Metal");

        if(isSupportedLookAndFeel(LafClass.windows)){
            lafs.put(LafClass.windows.getClassName(), "Windows");
        }

        if(isSupportedLookAndFeel(LafClass.gtk)){
            lafs.put(LafClass.gtk.getClassName(), "GTK");
        }

        if(isSupportedLookAndFeel(LafClass.synthetica)){
            lafs.put(LafClass.synthetica.getClassName(), "Synthetica");
        }

        if(isSupportedLookAndFeel(LafClass.jgoodiesWin)){
            lafs.put(LafClass.jgoodiesWin.getClassName(), "JGoodies Windows");
        }

        if(isSupportedLookAndFeel(LafClass.jgoodiesPl)){
            lafs.put(LafClass.jgoodiesPl.getClassName(), "JGoodies Plastic");
        }

        if(isSupportedLookAndFeel(LafClass.jgoodiesPl3D)){
            lafs.put(LafClass.jgoodiesPl3D.getClassName(), "JGoodies Plastic 3D");
        }

        if(isSupportedLookAndFeel(LafClass.jgoodiesPlXp)){
            lafs.put(LafClass.jgoodiesPlXp.getClassName(), "JGoodies Plastic XP");
        }

        if(isSupportedLookAndFeel(LafClass.quaqua)){
            lafs.put(LafClass.quaqua.getClassName(), "Quaqua");
        }
    }

    /**
     * {L&F class -> {theme label ~ identifier -> theme class name}}
     */
    public static final Map<String,Map<String,String>> lafThemes = new LinkedHashMap<String, Map<String, String>>();
    static {
        //noinspection unchecked
        lafThemes.put(LafClass.metal.getClassName(),
                      CollectionUtils.paramsToMap("Ocean", OceanTheme.class.getName(),
                                                  "Steel", DefaultMetalTheme.class.getName()));
        
        if(isSupportedLookAndFeel(LafClass.windows)){
            lafThemes.put(LafClass.windows.getClassName(),
                          Collections.<String,String>emptyMap());
        }

        if(isSupportedLookAndFeel(LafClass.gtk)){
            lafThemes.put(LafClass.gtk.getClassName(),
                          Collections.<String,String>emptyMap());
        }

        if(isSupportedLookAndFeel(LafClass.synthetica)){
            //noinspection unchecked
            lafThemes.put(LafClass.synthetica.getClassName(),
                          CollectionUtils.paramsToMap("Standard", SyntheticaStandardLookAndFeel.class.getName(),
                                                      "White Vision", SyntheticaWhiteVisionLookAndFeel.class.getName(),
                                                      "Black Eye", SyntheticaBlackEyeLookAndFeel.class.getName(),
                                                      "Simple 2D", SyntheticaSimple2DLookAndFeel.class.getName(),
                                                      "Sky Metallic", SyntheticaSkyMetallicLookAndFeel.class.getName(),
                                                      "Mauve Metallic", SyntheticaMauveMetallicLookAndFeel.class.getName(),
                                                      "Orange Metallic", SyntheticaOrangeMetallicLookAndFeel.class.getName(),
                                                      "Blue Steel", SyntheticaBlueSteelLookAndFeel.class.getName(),
                                                      "Blue Moon", SyntheticaBlueMoonLookAndFeel.class.getName(),
                                                      "Black Moon", SyntheticaBlackMoonLookAndFeel.class.getName(),
                                                      "Silver Moon", SyntheticaSilverMoonLookAndFeel.class.getName(),
                                                      "Blue Ice", SyntheticaBlueIceLookAndFeel.class.getName(),
                                                      "Green Dream", SyntheticaGreenDreamLookAndFeel.class.getName(),
                                                      "Black Star", SyntheticaBlackStarLookAndFeel.class.getName()
                                                    ));
        }

        if(isSupportedLookAndFeel(LafClass.jgoodiesWin)){
            lafThemes.put(LafClass.jgoodiesWin.getClassName(),
                          Collections.<String,String>emptyMap());
        }

        if(isSupportedLookAndFeel(LafClass.jgoodiesPl)){
            //noinspection unchecked
            lafThemes.put(LafClass.jgoodiesPl.getClassName(),
                          CollectionUtils.paramsToMap("Light Gray", LightGray.class.getName(),
                                                      "Silver", Silver.class.getName(),
                                                      "Desert Blue", DesertBlue.class.getName(),
                                                      "Desert Bluer", DesertBluer.class.getName(),
                                                      "Experience Blue", ExperienceBlue.class.getName(),
                                                      "Sky Blue", SkyBlue.class.getName()
                                                    ));
        }

        if(isSupportedLookAndFeel(LafClass.jgoodiesPl3D)){
            //noinspection unchecked
            lafThemes.put(LafClass.jgoodiesPl3D.getClassName(),
                          CollectionUtils.paramsToMap("Light Gray", LightGray.class.getName(),
                                                      "Silver", Silver.class.getName(),
                                                      "Desert Blue", DesertBlue.class.getName(),
                                                      "Desert Bluer", DesertBluer.class.getName(),
                                                      "Experience Blue", ExperienceBlue.class.getName(),
                                                      "Sky Blue", SkyBlue.class.getName()
                                                    ));
        }

        if(isSupportedLookAndFeel(LafClass.jgoodiesPlXp)){
            //noinspection unchecked
            lafThemes.put(LafClass.jgoodiesPlXp.getClassName(),
                          CollectionUtils.paramsToMap("Light Gray", LightGray.class.getName(),
                                                      "Silver", Silver.class.getName(),
                                                      "Desert Blue", DesertBlue.class.getName(),
                                                      "Desert Bluer", DesertBluer.class.getName(),
                                                      "Experience Blue", ExperienceBlue.class.getName(),
                                                      "Sky Blue", SkyBlue.class.getName()
                                                    ));
        }

        if(isSupportedLookAndFeel(LafClass.quaqua)){
            lafThemes.put(LafClass.quaqua.getClassName(),
                          Collections.<String,String>emptyMap());
        }
    }

    /**
     * {conf place -> label}
     */
    public static final Map<ConfigPlace,String> confPlaces = new LinkedHashMap<ConfigPlace,String>(3);
    static {
        confPlaces.put(ConfigPlace.app, Msg.defaultsConfPlacesApp.value()); //Application directory
        confPlaces.put(ConfigPlace.user, Msg.defaultsConfPlacesHome.value()); //User's home directory
        confPlaces.put(ConfigPlace.path, Msg.defaultsConfPlacesPath.value()); //Specified directory
    }

    /**
     * Application database version compatibility map.
     * <p>{db version supported by application code -> {persistece db version}}
     * <p>Compatibility check is successful if application code supports any
     * of persisted database. Version of persisted database is stored in database.
     */
    public static final Map<Integer, List<Integer>> dbVersionCompatibility = new HashMap<Integer, List<Integer>>();
    static {
        dbVersionCompatibility.put(1, CollectionUtils.itemsToList(1));
        dbVersionCompatibility.put(2, CollectionUtils.itemsToList(2));
    }

    //----------------------------------------------------------------------

    private static boolean isSupportedLookAndFeel(LafClass lafClass){
        try {
            Class c = (ClassLoader.getSystemClassLoader().loadClass(lafClass.getClassName()));
            Method m = c.getMethod("isSupportedLookAndFeel");
            Object r = m.invoke(c.newInstance());
            if(r != null && r instanceof Boolean && Boolean.TRUE.equals(r)){
                return true;
            }
        } catch (ClassNotFoundException e) {
            log.info(LogMsg.toString("Look and Feel is not supported because it is missing in classpath",
                                     "lafClass", lafClass, "exception", e.toString()));
        } catch (Exception e) {
            log.warn(LogMsg.toString("Look and Feel is not supported because an error occurred during check for support",
                                     "lafClass", lafClass), e);
        }
        return false;
    }


}
